//
// Created by Felix on 24-5-16.
//

#ifndef GAZE_CAMERACONTROLLER_HPP
#define GAZE_CAMERACONTROLLER_HPP

#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/core/macro/component.hpp"
#include "oatpp/core/macro/codegen.hpp"

#include "common.hpp"

#include "service/LocalizationService.hpp"
#include "service/CameraService.hpp"

#include "dto/CameraUpdateDetailsDto.hpp"
#include "validate/CameraUpdateDetailsDtoValidate.hpp"

#include "dto/CameraUpdateStatusDto.hpp"
#include "validate/CameraUpdateStatusDtoValidate.hpp"

#include OATPP_CODEGEN_BEGIN(ApiController)

class CameraController : public oatpp::web::server::api::ApiController {
public:
    explicit CameraController(
            OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)
    ) : oatpp::web::server::api::ApiController(objectMapper) {}

    static std::shared_ptr<CameraController> createShared(
            OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)
    ) {
        return std::make_shared<CameraController>(objectMapper);
    }

private:
    LocalizationService iLocalizationService;
    CameraService iCameraService;
public:
    ENDPOINT_INFO(createCamera) {
        info->addTag("Camera");
        info->summary = "创建摄像头";
        info->authorization = ""; // <-- 没有这一行，无法声明需要授权
        info->addSecurityRequirement("basic_auth");
        info->addConsumes < Object < CameraCreateDto >> ("application/json");
        info->addResponse < Object < MessageDtoComposeCameraResponseDto > > (Status::CODE_200, "application/json");
        info->addResponse < Object < MessageDto<> >> (Status::CODE_401,
                "application/json", R"(输出：{"status_code":401,"status":"ERROR","message":"Unauthorized","data":[]})"
        );
        info->addResponse < Object < MessageDto<> >> (Status::CODE_422, "application/json");
    } // Create camera
    ENDPOINT("POST", "/api/cameras", createCamera,
             REQUEST(std::shared_ptr<IncomingRequest>, request),
             BODY_DTO(Object < CameraCreateDto > , cameraCreateDto)) {
        cameraCreateDto->title = trim(cameraCreateDto->title);
        OATPP_ASSERT_HTTP(
                !cameraCreateDto->title->empty(),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid Title. Must not be empty or too short.",
                        request->getHeader("Accept-Language")
                )
        )

        auto message = MessageDtoComposeCameraResponseDto::createShared();
        message->status = "OK";
        message->statusCode = 200;
        message->message = "创建成功";
        message->data = iCameraService.createCamera(cameraCreateDto);
        return createDtoResponse(Status::CODE_200, message);
    }

    ENDPOINT_INFO(updateCameraDetails) {
        info->addTag("Camera");
        info->summary = "更新摄像头信息";
        info->description = "role 支持 [ ROLE_GUEST , ROLE_ADMIN ]。<br/>这接口不支持修改密码。";
        info->authorization = ""; // <-- 没有这一行，无法声明需要授权
        info->addSecurityRequirement("basic_auth");
        info->addConsumes < Object < CameraUpdateDetailsDto >> ("application/json");
        info->addResponse < Object < MessageDtoComposeCameraResponseDto >> (Status::CODE_200, "application/json");
        info->addResponse < Object < MessageDto<> >> (Status::CODE_401,
                "application/json", R"(输出：{"status_code":401,"status":"ERROR","message":"Unauthorized","data":[]})"
        );
        info->addResponse < Object < MessageDto<> >> (Status::CODE_422, "application/json");
    } // Update camera details
    ENDPOINT("PUT", "/api/cameras/{camera_id}", updateCameraDetails,
             REQUEST(std::shared_ptr<IncomingRequest>, request),
             PATH(Int32, cameraId, "camera_id"),
             BODY_DTO(Object < CameraUpdateDetailsDto > , cameraUpdateDetailsDto)) {
        OATPP_ASSERT_HTTP(
                CameraUpdateDetailsDtoValidate::validateRequireCameraId(iCameraService, cameraId),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid CameraId.CameraId is required and must refer to an existing camera.",
                        request->getHeader("Accept-Language")
                )
        )
        cameraUpdateDetailsDto->cameraId = cameraId;
        cameraUpdateDetailsDto->title = trim(cameraUpdateDetailsDto->title);
        OATPP_ASSERT_HTTP(
                !cameraUpdateDetailsDto->title->empty(),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid Title. Must not be empty or too short.",
                        request->getHeader("Accept-Language")
                )
        )
        OATPP_ASSERT_HTTP(
                CameraUpdateDetailsDtoValidate::validateRequireStatus(cameraUpdateDetailsDto),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid Status.The Status field cannot be empty or contain an invalid value.",
                        request->getHeader("Accept-Language")
                )
        )

        auto message = MessageDtoComposeCameraResponseDto::createShared();
        message->status = "OK";
        message->statusCode = 200;
        message->message = "修改成功";
        message->data = iCameraService.updateCameraDetails(cameraUpdateDetailsDto);
        return createDtoResponse(Status::CODE_200, message);
    }

    ENDPOINT_INFO(updateCameraStatus) {
        info->addTag("Camera");
        info->summary = "修改摄像头状态";
        info->description = "";
        info->authorization = ""; // <-- 没有这一行，无法声明需要授权
        info->addSecurityRequirement("basic_auth");
        info->addConsumes < Object < CameraUpdateStatusDto > > ("application/json");
        info->addResponse < Object < MessageDtoComposeCameraResponseDto > > (Status::CODE_200, "application/json");
        info->addResponse < Object < MessageDto<> >> (Status::CODE_401,
                "application/json", R"(输出：{"status_code":401,"status":"ERROR","message":"Unauthorized","data":[]})"
        );
        info->addResponse < Object < MessageDto<> >> (Status::CODE_422, "application/json");
    } // Update camera status
    ENDPOINT("PATCH", "/api/cameras/{camera_id}/status", updateCameraStatus,
             REQUEST(std::shared_ptr<IncomingRequest>, request),
             PATH(Int32, cameraId, "camera_id"),
             BODY_DTO(Object < CameraUpdateStatusDto > , cameraUpdateStatusDto)) {
        OATPP_ASSERT_HTTP(
                CameraUpdateStatusDtoValidate::validateRequireCameraId(iCameraService, cameraId),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid CameraId.CameraId is required and must refer to an existing camera.",
                        request->getHeader("Accept-Language")
                )
        )
        cameraUpdateStatusDto->cameraId = cameraId;
        OATPP_ASSERT_HTTP(
                CameraUpdateStatusDtoValidate::validateRequireStatus(cameraUpdateStatusDto),
                Status::CODE_422,
                iLocalizationService.getHttpMessage(
                        "Invalid Status.The Status field cannot be empty or contain an invalid value.",
                        request->getHeader("Accept-Language")
                )
        )

        auto message = MessageDtoComposeCameraResponseDto::createShared();
        message->status = "OK";
        message->statusCode = 200;
        message->message = "修改成功";
        message->data = iCameraService.updateCameraStatus(cameraUpdateStatusDto);
        return createDtoResponse(Status::CODE_200, message);
    }

    ENDPOINT_INFO(getCameraById) {
        info->addTag("Camera");
        info->summary = "获得用户";
        info->description = "";
        info->authorization = ""; // <-- 没有这一行，无法声明需要授权
        info->addSecurityRequirement("basic_auth");
        info->addResponse < Object < MessageDtoComposeCameraResponseDto > > (Status::CODE_200, "application/json");
        info->addResponse < Object < MessageDto<> > > (Status::CODE_401,
                "application/json", R"(输出：{"status_code":401,"status":"ERROR","message":"Unauthorized","data":[]})"
        );
        info->addResponse < Object < MessageDto<> > > (Status::CODE_422, "application/json");
    } // get cameras by id
    ENDPOINT("GET", "/api/cameras/{camera_id}", getCameraById,
             PATH(Int32, cameraId, "camera_id")) {
        auto message = MessageDtoComposeCameraResponseDto::createShared();
        message->status = "OK";
        message->statusCode = 200;
        message->message = "获得成功";
        message->data = iCameraService.getCameraById(cameraId);
        return createDtoResponse(Status::CODE_200, message);
    }

    ENDPOINT_INFO(getCameras) {
        info->addTag("Camera");
        info->summary = "获得摄像头列表";
        info->description = "";
        info->authorization = ""; // <-- 没有这一行，无法声明需要授权
        info->addSecurityRequirement("basic_auth");
        info->pathParams["page"].addExample("page", oatpp::String("1"));
        info->pathParams["page_size"].addExample("page_size", oatpp::String("10"));
        info->queryParams["keyWords"].required = false;
        info->queryParams["model"].required = false;
        info->queryParams["status"].required = false;
        info->addResponse < Object < MessageDtoComposePageOfCameras >> (Status::CODE_200, "application/json");
        info->addResponse < Object < MessageDto<> >> (Status::CODE_401,
                "application/json", R"(输出：{"status_code":401,"status":"ERROR","message":"Unauthorized","data":[]})"
        );
        info->addResponse < Object < MessageDto<> >> (Status::CODE_422, "application/json");
    } // Get cameras
    ENDPOINT("GET", "/api/cameras/page/{page}/page_size/{page_size}", getCameras,
             PATH(Int32, page),
             PATH(Int32, pageSize, "page_size"),
             QUERY(String, keyWords, "keyWords", ""),
             QUERY(String, model, "model", ""),
             QUERY(Int8, status, "status", 1 - 1)) {
        auto queryDto = CameraServiceGetAllCameraQueryDto::createShared();
        queryDto->keyWords = keyWords;
        queryDto->model = model;
        queryDto->status = status;

        auto message = MessageDtoComposePageOfCameras::createShared();
        message->status = "OK";
        message->statusCode = 200;
        message->message = "获得成功";
        message->data = iCameraService.getAllCamera(page, pageSize, queryDto);
        return createDtoResponse(Status::CODE_200, message);
    }
};

#include OATPP_CODEGEN_END(ApiController)

#endif //GAZE_CAMERACONTROLLER_HPP
